/*
 * Copyright 2007 Agile Plugins Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * 	http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.googlecode.agileplugins.monkey;

import com.intellij.codeInspection.*;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.refactoring.rename.RenameProcessor;
import com.intellij.util.IncorrectOperationException;

public class RenameWiredFieldInspection extends LocalInspectionTool {

    public String getGroupDisplayName() {
        return "PurpleMonkeyDishwasher";
    }

    public String getDisplayName() {
        return "Rename test wired fields";
    }

    public String getShortName() {
        return "RenameWiredField";
    }

    public boolean isEnabledByDefault() {
        return true;
    }

    public ProblemDescriptor[] checkMethod(PsiMethod method, InspectionManager manager, boolean isOnTheFly) {
        if (!method.getName().equals("setUpFixtures")) {
            return null;
        }
        PsiCodeBlock body = method.getBody();
        if (body == null) {
            return null;
        }
        PsiStatement[] statements = body.getStatements();
        for (int i = 0; i < statements.length; i++) {
            PsiStatement statement = statements[i];
            if (statement instanceof PsiExpressionStatement) {
                PsiExpressionStatement psiExpressionStatement = (PsiExpressionStatement) statement;
                PsiExpression expression = psiExpressionStatement.getExpression();
                if (expression instanceof PsiMethodCallExpression) {
                    PsiMethodCallExpression psiMethodCallExpression = (PsiMethodCallExpression) expression;
                    PsiReferenceExpression methodExpression = psiMethodCallExpression.getMethodExpression();
                    PsiMethod psiMethod = (PsiMethod) methodExpression.resolve();
                    if (psiMethod != null && psiMethod.getName().equals("resolveFieldsByType")) {
                        return new ProblemDescriptor[]{
                                manager.createProblemDescriptor(psiMethodCallExpression,
                                        "This call could be removed by prefixing fields with 'wired'",
                                        new RenameWiredFieldsQuickFix(), ProblemHighlightType.LIKE_DEPRECATED)
                        };
                    }
                }

            }
        }
        return null;
    }

    private String ucFirst(String name) {
        return name.substring(0, 1).toUpperCase() + name.substring(1);
    }

    private class RenameWiredFieldsQuickFix implements LocalQuickFix {

        public String getName() {
            return "Remove resolveFieldsByType() call by renaming fields";
        }


        public void applyFix(Project project, ProblemDescriptor problemdescriptor) {
            PsiMethodCallExpression psiMethodCallExpression = (PsiMethodCallExpression) problemdescriptor.getPsiElement();
            PsiClass containingClass = PsiUtil.getContainingClass(psiMethodCallExpression);
            PsiField[] fields = containingClass.getFields();
            PsiExpressionList argumentList = psiMethodCallExpression.getArgumentList();
            PsiExpression[] expressions = argumentList.getExpressions();
            if (expressions.length == 1 && expressions[0] instanceof PsiNewExpression) {
                PsiNewExpression exp = (PsiNewExpression) expressions[0];
                PsiArrayInitializerExpression arrayInitializer = exp.getArrayInitializer();
                PsiExpression[] initializers = arrayInitializer.getInitializers();
                try {
                    PsiElement statement = psiMethodCallExpression.getParent();
                    PsiCodeBlock codeBlock = (PsiCodeBlock) statement.getParent();
                    if (codeBlock.getStatements().length == 1) {
                        codeBlock.getParent().delete();
                    } else {
                        psiMethodCallExpression.getParent().delete();
                    }
                } catch (IncorrectOperationException e) {
                    throw new RuntimeException(e);
                }
                for (int j = 0; j < initializers.length; j++) {
                    PsiExpression initializer = initializers[j];
                    if (initializer instanceof PsiLiteralExpression) {
                        PsiLiteralExpression psiLiteralExpression = (PsiLiteralExpression) initializer;
                        String value = (String) psiLiteralExpression.getValue();
                        System.out.println("value = " + value);
                        if (value != null && !value.startsWith("wired")) {
                            for (int i = 0; i < fields.length; i++) {
                                PsiField field = fields[i];
                                if (value.equals(field.getName())) {
                                    String newName = "wired" + ucFirst(value);
                                    RenameProcessor renameprocessor = new RenameProcessor(project, field, newName,
                                            false, false);
                                    renameprocessor.run();
                                }
                            }
                        }
                    }
                }
            }
        }

        public String getFamilyName() {
            return "PurpleMonkeyDishwasher";
        }
    }
}
